package com.yuandian.customer.perception.controller;

import cn.hutool.core.convert.Convert;
import com.yuandian.api.customer_perception.po.OperatorOverviewParams;
import com.yuandian.api.customer_perception.po.OperatorResolutionParams;
import com.yuandian.api.customer_perception.vo.OperatorBusiDetailListVo;
import com.yuandian.api.customer_perception.vo.OperatorResolutionListVo;
import com.yuandian.api.customer_perception.vo.OperatorStatisticsListVo;
import com.yuandian.api.customer_perception.vo.SearchOptionVo;
import com.yuandian.api.management.entity.ConfBusiness;
import com.yuandian.api.management.feign.RemoteAreaService;
import com.yuandian.api.management.feign.RemoteBusinessHallService;
import com.yuandian.api.management.feign.RemoteBusinessService;
import com.yuandian.bpm.common.core.constant.CommonConstants;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.customer.perception.service.IOperatorResolutionService;
import com.yuandian.enums.S;
import com.yuandian.utils.BeanUtils;
import com.yuandian.utils.PageDataInfo;
import com.yuandian.utils.StringUtils;
import com.yuandian.utils.YDateUtil;
import com.yuandian.utils.poi.ExcelTitleUtils;
import com.yuandian.utils.poi.ExcelUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.*;


/**
 * <p> 操作员分析Controller </p>
 *
 * @Author: LinSheHi
 * @Date: 2021/8/16 10:03
 */
@Slf4j
@Api(value = "操作员分析接口", tags = "操作员分析接口")
@RestController
@RequestMapping("/operator/analysis")
public class OperatorResolutionController {

	@Autowired
	private IOperatorResolutionService operatorResolutionService;


    @Autowired
    private RemoteAreaService remoteAreaService;

    @Autowired
    private RemoteBusinessHallService remoteBusinessHallService;

    @Autowired
    private RemoteBusinessService remoteBusinessService;

    private final String[] completionState = new String[]{"不完整", "完整"};

    private final String[] dealState = new String[]{"失败", "成功"};


    /**
     * 业务办理列表
     *
     * @param params 请求参数
     * @return 通用返回对象
     */
    @PostMapping("/businessProcessList")
	@ApiOperation(value = "操作员分析-查询系统分析概况", notes = "操作员分析-查询系统分析概况")
	public R<Object> queryBusinessProcessList(@RequestBody OperatorResolutionParams params) {
        return operatorResolutionService.queryBusinessProcessList(params);
    }


    /**
     * 业务办理列表下载
     *
     * @param params 请求参数
     * @return 业务办理列表下载
     */
    @ResponseBody
	@ApiOperation(value = "操作员分析-业务办理列表下载", notes = "操作员分析-业务办理列表下载")
	@PostMapping("/businessProcessListExport")
    public void queryBusinessProcessListExport(@RequestBody OperatorResolutionParams params, HttpServletResponse response) throws IOException, ParseException {

        List<OperatorResolutionListVo> resList = new ArrayList<>();
        try {
            resList = operatorResolutionService.queryBusinessProcessListExport(params);
        } catch (Exception e) {
            log.error("所选时间表不存在!但表格需要正常导出.");
        }
        String title = "办理业务列表";
        // 文件名
        String fileName = title + System.currentTimeMillis();

        // 表单大标题
        List<String> titleParams = new ArrayList<>();
        titleParams.add(title);
        if (params.getAreaCode() != null && !Objects.equals(params.getAreaCode(), "")) {
            R<String> nameRes = remoteAreaService.queryAreaName(params.getAreaCode());
            if (nameRes.getCode() == CommonConstants.FAIL){
                log.error("远程调用配置系统获取区域名称失败,错误：{}",nameRes.getMsg());
            }
            titleParams.add(nameRes.getData());
        }
        if (params.getBusinessHallId() != null && !Objects.equals(params.getBusinessHallId(), "")) {
            R<String> nameRes = remoteBusinessHallService.queryBusinessHallNameById(params.getBusinessHallId());
            if (nameRes.getCode() == CommonConstants.FAIL){
                log.error("远程调用配置系统获取营业厅名称失败,错误：{}",nameRes.getMsg());
            }
            titleParams.add(nameRes.getData());
        }
        String formTitleName = ExcelTitleUtils.formTitleName(titleParams,params.getStartTime(),params.getEndTime());

        // 表单大标题合并单元格
        List<List<String>> headList = new ArrayList<>();
        List<String> titleList = Arrays.asList("序号","地市",params.getOfficeName()+"ID", params.getOfficeName()+"名称","操作员ID", "姓名","系统", "业务使用数量",  "访问量", "受理量", "告警访问量","失败访问量", "平均办理时长", "成功率");
        titleList.forEach(s -> {
            List<String> childHeadList = new ArrayList<>();
            childHeadList.add(formTitleName);
            childHeadList.add(s);
            headList.add(childHeadList);
        });

        //回填序号
        int index = 1;
        for (OperatorResolutionListVo vo : resList) {
            vo.setId(index++);
            if (StringUtils.isEmpty(vo.getAreaCode())) { vo.setAreaCode("-"); }
            if (StringUtils.isEmpty(vo.getBusinessHallId())) { vo.setBusinessHallId("-"); }
			if (StringUtils.isEmpty(vo.getOperatorId())) { vo.setOperatorId("-"); }
            if (StringUtils.isEmpty(vo.getBusinessHallName())) {
                if (Objects.equals(vo.getBusinessHallId(), "-")) {
                    vo.setBusinessHallName("-");
                } else {
                    vo.setBusinessHallName("未知");
                }
            }

			if (vo.getAreaName() == null || vo.getAreaName().equals("")) {
				if (Objects.equals(vo.getAreaCode(), "-")) {
					vo.setAreaName("-");
				} else {
					vo.setAreaName("未知");
				}
			}

            if (StringUtils.isEmpty(vo.getOperatorName())) {
                if (Objects.equals(vo.getOperatorId(), "-")) {
                    vo.setOperatorName("-");
                } else {
                    vo.setOperatorName("未知");
                }
            }
        }
        // 数据整理加上百分号
        resList.forEach(operatorResolutionListVo -> {
            if (operatorResolutionListVo.getAvgVisitTime() == null) {
                operatorResolutionListVo.setAvgVisitTime("0.00毫秒");
            } else {
                operatorResolutionListVo.setAvgVisitTime(YDateUtil.getMinSecond(getDouble(Double.parseDouble(operatorResolutionListVo.getAvgVisitTime()) / 1000)));
            }
            operatorResolutionListVo.setSuccessRate(operatorResolutionListVo.getSuccessRate() == null ? "" :  (operatorResolutionListVo.getSuccessRate() + "%"));
        });
        ExcelUtil.writeExcel(OperatorResolutionListVo.class, fileName, title, resList, headList, response);
    }


    /**
     * 办理业务统计列表
     *
     * @param params 请求参数
     * @return 通用返回对象
     */
    @PostMapping("/businessProcessStatisticsList")
	@ApiOperation(value = "操作员分析-业务办理列表下载", notes = "操作员分析-业务办理列表下载")
	public R<Object> queryBusinessProcessStatisticsList(@RequestBody OperatorResolutionParams params) {
        return operatorResolutionService.queryBusinessProcessStatisticsList(params);
    }


    /**
     * 业务办理统计列表下载
     *
     * @param params 请求参数
     * @return 业务办理详情列表下载
     */
    @ResponseBody
    @PostMapping("/businessProcessStatisticsListExport")
	@ApiOperation(value = "操作员分析-业务办理列表下载", notes = "操作员分析-业务办理列表下载")
	public void queryBusinessProcessStatisticsListExport(@RequestBody OperatorResolutionParams params, HttpServletResponse response) throws IOException, ParseException {

        List<OperatorStatisticsListVo> resList = new ArrayList<>();
        try {
            resList = operatorResolutionService.queryBusinessProcessStatisticsListExport(params);
        } catch (Exception e) {
            log.error("所选时间表不存在!但表格需要正常导出.");
        }
        String title = "办理业务统计列表";

        // 表单大标题
        List<String> titleParams = new ArrayList<>();
        titleParams.add(title);
        titleParams.add(params.getSystemName());
        if (params.getBusinessCode() != null && !Objects.equals(params.getBusinessCode(), "")) {
            R<ConfBusiness> businessR = remoteBusinessService.getBusinessByBusinessCode(params.getBusinessCode());
            if (businessR.getCode() == CommonConstants.FAIL){
                log.error("远程调用配置系统获取业务信息失败,错误：{}",businessR.getMsg());
            }
            titleParams.add(businessR.getData().getName());
        }
        if (params.getAreaCode() != null && !Objects.equals(params.getAreaCode(), "")) {
            R<String> nameRes = remoteAreaService.queryAreaName(params.getAreaCode());
            if (nameRes.getCode() == CommonConstants.FAIL){
                log.error("远程调用配置系统获取区域名称失败,错误：{}",nameRes.getMsg());
            }
            titleParams.add(nameRes.getData());
        }
        if (params.getBusinessHallId() != null && !Objects.equals(params.getBusinessHallId(), "")) {
            R<String> nameRes = remoteBusinessHallService.queryBusinessHallNameById(params.getBusinessHallId());
            if (nameRes.getCode() == CommonConstants.FAIL){
                log.error("远程调用配置系统获取营业厅名称失败,错误：{}",nameRes.getMsg());
            }
            titleParams.add(nameRes.getData());
        }
        titleParams.add(params.getOperatorName());
        String formTitleName = ExcelTitleUtils.formTitleName(titleParams,params.getStartTime(),params.getEndTime());

        // 表单大标题合并单元格
        List<List<String>> headList = new ArrayList<>();
        List<String> titleList = Arrays.asList("业务名称", "系统名称",  "访问量","受理量",  "告警访问量","失败访问量", "平均办理时长", "平均响应时长", "成功率", "健康度");
        titleList.forEach(s -> {
            List<String> childHeadList = new ArrayList<>();
            childHeadList.add(formTitleName);
            childHeadList.add(s);
            headList.add(childHeadList);
        });

        // 数据整理加上百分号
        resList.forEach(operatorResolutionListVo -> {
            operatorResolutionListVo.setAvgResponseTime(YDateUtil.getMinSecond(getDouble(Double.parseDouble(operatorResolutionListVo.getAvgResponseTime()) / 1000)));
            operatorResolutionListVo.setAvgVisitTime(YDateUtil.getMinSecond(getDouble(Double.parseDouble(operatorResolutionListVo.getAvgVisitTime()) / 1000)));

            operatorResolutionListVo.setSuccessRate(operatorResolutionListVo.getSuccessRate() == null ? "" : (operatorResolutionListVo.getSuccessRate() + "%"));
            operatorResolutionListVo.setHealthRate(operatorResolutionListVo.getHealthRate() == null ? "" : (operatorResolutionListVo.getHealthRate() + "%"));
        });
        ExcelUtil.writeExcel(OperatorStatisticsListVo.class, "", title, resList, headList, response);
    }


    /**
     * 业务办理明细列表
     *
     * @param params 请求参数
     * @return 通用返回对象
     */
    @PostMapping("/businessProcessDetailList")
	@ApiOperation(value = "操作员分析-业务办理列表下载", notes = "操作员分析-业务办理列表下载")
	public R<Object> queryBusinessProcessDetailList(@RequestBody OperatorResolutionParams params) {
        return operatorResolutionService.queryBusinessProcessDetailList(params);
    }

    /**
     * 业务办理明细列表下载
     *
     * @param params 请求参数
     * @return 业务办理明细列表下载
     */
    @ResponseBody
    @PostMapping("/businessProcessDetailListExport")
	@ApiOperation(value = "操作员分析-业务办理明细列表下载", notes = "操作员分析-业务办理明细列表下载")
	public void queryBusinessProcessDetailListExport(@RequestBody OperatorResolutionParams params, HttpServletResponse response)
			throws IOException {
		List<OperatorBusiDetailListVo> resList = new ArrayList<>();
		params.setPageNum(1);
		params.setPageSize(1000000L);
		PageDataInfo pageDataInfo = BeanUtils.cast(operatorResolutionService.queryBusinessProcessDetailList(params).getData());
		resList = BeanUtils.cast(pageDataInfo.getData());

        try {
			R<Object> r = operatorResolutionService.queryBusinessProcessDetailList(params);
			Object data = r.getData();
		} catch (Exception e) {
            log.error("所选时间表不存在!但表格需要正常导出.");
        }

        OperatorOverviewParams p = new OperatorOverviewParams();
        p.setAreaCode(params.getAreaCode());
        R<List<SearchOptionVo>> listR = remoteBusinessHallService.queryBusinessHall(p);
        if (listR.getCode() == CommonConstants.FAIL) {
            log.error("远程调用配置系统获取获取营业厅数据失败，错误：{}", listR.getMsg());
        }
        List<SearchOptionVo> list = listR.getData();
        Map<String, String> mapVo = new HashMap<>();
        for (SearchOptionVo searchOptionVo : list) {
            mapVo.put(searchOptionVo.getCode(), searchOptionVo.getValue());
        }

        //回填序号
        int index = 1;

        //获取areaCode和areaNameMap集合
        Map<String,String> areaMap = new HashMap<>();
        R<List<Map<String, String>>> areaCodeAndNameRes = remoteAreaService.getAreaCodeAndName();
        if (areaCodeAndNameRes.getCode() == CommonConstants.FAIL){
            log.error("远程调用配置系统获取区域信息失败,错误：{}",areaCodeAndNameRes.getMsg());
        }
		List<Map<String, String>> maps = areaCodeAndNameRes.getData();

        for (Map<String, String> map : maps) {
            areaMap.put(map.get("areaCode"),map.get("areaName"));
        }
		for (OperatorBusiDetailListVo vo : resList) {
			vo.setId(index++);
            vo.setDealState(dealState[Convert.toInt(vo.getDealState())]);
            vo.setCompletionState(completionState[Convert.toInt(vo.getCompletionState())]);
            vo.setDealTime(YDateUtil.getMinSecond(getDouble(Double.parseDouble(vo.getDealTime()) / 1000)));
            vo.setClientFreeTime(YDateUtil.getMinSecond(getDouble(Double.parseDouble(vo.getClientFreeTime()) / 1000)));

            if (StringUtils.isEmpty(vo.getAreaName())) {  vo.setAreaName("未知"); }
            if (StringUtils.isEmpty(vo.getBusinessHallId())) { vo.setBusinessHallId("-"); }
			if (StringUtils.isEmpty(vo.getOperatorId())) { vo.setOperatorId("-"); }
			if (StringUtils.isEmpty(vo.getUserIdentify())) { vo.setUserIdentify("-"); }
            if (vo.getBusinessHallName() == null || vo.getBusinessHallName().equals("")) {
                if (vo.getBusinessHallId() == "-") {
                    vo.setBusinessHallName("-");
                } else {
                    vo.setBusinessHallName("未知");
                }
            }
        }

        String title = "办理业务明细列表";
        // 表单大标题
        List<String> titleParams = new ArrayList<>();
        titleParams.add(title);
        if (params.getSystemName() != null && !"".equals(params.getSystemName())) {
            titleParams.add(params.getSystemName());
        }
        if (params.getBusinessCode() != null && !"".equals(params.getBusinessCode())) {
            R<ConfBusiness> businessR = remoteBusinessService.getBusinessByBusinessCode(params.getBusinessCode());
            if (businessR.getCode() == CommonConstants.FAIL){
                log.error("远程调用配置系统获取业务信息失败,错误：{}",businessR.getMsg());
            }
            titleParams.add(businessR.getData().getName());
        }
        if (params.getAreaCode() != null && !Objects.equals(params.getAreaCode(), "")) {
            R<String> nameRes = remoteAreaService.queryAreaName(params.getAreaCode());
            if (nameRes.getCode() == CommonConstants.FAIL){
                log.error("远程调用配置系统获取区域名称失败,错误：{}",nameRes.getMsg());
            }
            titleParams.add(nameRes.getData());
        }
        if (params.getBusinessHallId() != null && !Objects.equals(params.getBusinessHallId(), "")) {
            R<String> nameRes = remoteBusinessHallService.queryBusinessHallNameById(params.getBusinessHallId());
            if (nameRes.getCode() == CommonConstants.FAIL){
                log.error("远程调用配置系统获取营业厅名称失败,错误：{}",nameRes.getMsg());
            }
            titleParams.add(nameRes.getData());
        }
        if (params.getOperatorName() != null && !params.getOperatorName().equals("")) {
            titleParams.add(params.getOperatorName());
        }
        String formTitleName = ExcelTitleUtils.formTitleName(titleParams,params.getStartTime(),params.getEndTime());

        // 表单大标题合并单元格
        List<List<String>> headList = new ArrayList<>();
        List<String> titleList = Arrays.asList("序号","业务名称", "所属系统", "自定义返回码", "操作员ID", "地区",
                params.getOfficeName()+"ID", params.getOfficeName()+"名称", "用户标识","开始时间", "结束时间", "业务状态", "完整性", "办理时长", "空闲时长", "业务告警量");
        titleList.forEach(s -> {
            List<String> childHeadList = new ArrayList<>();
            childHeadList.add(formTitleName);
            childHeadList.add(s);
            headList.add(childHeadList);
        });

        ExcelUtil.writeExcel(OperatorBusiDetailListVo.class, formTitleName, title, resList, headList, response);
    }


    /**
     * 操作员业务办理量
     *
     * @param params 请求参数
     * @return 通用返回对象
     */
    @PostMapping("/operatorBusinessProcessCount")
	@ApiOperation(value = "操作员分析-操作员业务办理量", notes = "操作员分析-操作员业务办理量")
	public R<Object> queryOperatorBusinessProcessCount(@RequestBody OperatorResolutionParams params) {
        return operatorResolutionService.queryOperatorBusinessProcessCount(params);
    }

    /**
     * 操作员人工操作平均耗时
     *
     * @param params 请求参数
     * @return 通用返回对象
     */
    @PostMapping("/operatorAvgDealTime")
	@ApiOperation(value = "操作员分析-操作员人工操作平均耗时", notes = "操作员分析-操作员人工操作平均耗时")
	public R<Object> queryOperatorAvgDealTime(@RequestBody OperatorResolutionParams params) {
        return operatorResolutionService.queryOperatorAvgDealTime(params);
    }

    /**
     * 操作员办理业务占比
     *
     * @param params 请求参数
     * @return 通用返回对象
     */
    @PostMapping("/operatorBusinessPercent")
	@ApiOperation(value = "操作员分析-操作员办理业务占比", notes = "操作员分析-操作员办理业务占比")
	public R<Object> queryOperatorBusinessPercent(@RequestBody OperatorResolutionParams params) {
        return operatorResolutionService.queryOperatorBusinessPercent(params);
    }

    /**
     * 操作员办理业务告警类型
     *
     * @param params 请求参数
     * @return 通用返回对象
     */
    @PostMapping("/operatorAlarmTypeCount")
	@ApiOperation(value = "操作员分析-操作员办理业务告警类型", notes = "操作员分析-操作员办理业务告警类型")
	public R<Object> queryOperatorAlarmTypeCount(@RequestBody OperatorResolutionParams params) {
        return operatorResolutionService.queryOperatorAlarmTypeCount(params);
    }

    /**
     * 操作员办理业务平均耗时
     *平均时长-busi_sys_detail_stat_m-KhgzBusinessDetailStatTask-操作员办理业务平均耗时趋势图-延迟3分钟--/operator/analysis/operatorBusinessAvgVisitTime
     * @param params 请求参数
     * @return 通用返回对象
     */
    @PostMapping("/operatorBusinessAvgVisitTime")
	@ApiOperation(value = "操作员分析-操作员办理业务平均耗时", notes = "操作员分析-操作员办理业务平均耗时")
	public R<Object> queryOperatorBusinessAvgVisitTime(@RequestBody OperatorResolutionParams params) {
        return operatorResolutionService.queryOperatorBusinessAvgVisitTime(params);
    }

    /**
     * 操作员办理X业务趋势图
     * 业务告警量,业务受理量,业务访问量,业务失败量-busi_sys_detail_stat_m-KhgzBusinessDetailStatTask-操作员办理趋势图-延迟3分钟-/api-khgz/modules/operator/analysis/operatorBusinessLine
     * @param params 请求参数
     * @return 通用返回对象
     */
    @PostMapping("/operatorBusinessLine")
	@ApiOperation(value = "操作员分析-操作员办理X业务趋势图", notes = "操作员分析-操作员办理X业务趋势图")
	public R<Object> queryOperatorBusinessLine(@RequestBody OperatorResolutionParams params) {
        return operatorResolutionService.queryOperatorBusinessLine(params);
    }

    /**
     * 根据查询条件查询某业务员操作过的所有系统
     *
     * @param params 请求参数
     * @return 通用返回对象
     */
    @PostMapping("/querySystemListByOperator")
	@ApiOperation(value = "操作员分析-根据查询条件查询某业务员操作过的所有系统", notes = "操作员分析-根据查询条件查询某业务员操作过的所有系统")
	public R<Object> querySystemListByOperator(@RequestBody OperatorResolutionParams params) {
        return operatorResolutionService.querySystemListByOperator(params);
    }

    /**
     * 根据查询条件查询某业务员操作过的所有业务
     *
     * @param params 请求参数
     * @return 通用返回对象
     */
    @PostMapping("/queryBusinessListByOperator")
	@ApiOperation(value = "操作员分析-根据查询条件查询某业务员操作过的所有业务", notes = "操作员分析-根据查询条件查询某业务员操作过的所有业务")
	public R<Object> queryBusinessListByOperator(@RequestBody OperatorResolutionParams params) {
        return operatorResolutionService.queryBusinessListByOperator(params);
    }


    public static Double getDouble(Double allTime) {
        if (allTime == null) {
            return 0d;
        }
        return new BigDecimal(allTime).setScale(2, RoundingMode.HALF_UP).doubleValue();
    }

}
